package com.guaoran.common.utils;

import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;

public class DateTimeUtil {

	public static int FIRST_DAY_OF_WEEK = Calendar.MONDAY; // 中国周一是一周的第一天
	public static long HOUR_VARIABLE = 60 * 1000;

	/**
	 * 取得日期所在月包含的天数
	 * 
	 * @param date
	 * @return
	 */
	public static int getDaysOfMonth(Date date) {
		Calendar c = getCalendar();
		c.setTime(date);
		return c.getActualMaximum(Calendar.DAY_OF_MONTH);
	}

	/**
	 * 取得月第一天
	 * 
	 * @param date
	 * @return
	 */
	public static Date getFirstDateOfMonth(Date date) {
		Calendar c = getCalendar();
		c.setTime(date);
		c.set(Calendar.DAY_OF_MONTH, c.getActualMinimum(Calendar.DAY_OF_MONTH));
		c.set(Calendar.HOUR_OF_DAY, c.getActualMinimum(Calendar.HOUR_OF_DAY));
		c.set(Calendar.MINUTE, c.getActualMinimum(Calendar.MINUTE));
		c.set(Calendar.SECOND, c.getActualMinimum(Calendar.SECOND));
		return c.getTime();
	}

	public static Long getUtcDate(Date date) {
		Calendar cal = getCalendar();
		cal.setTimeZone(TimeZone.getDefault());
		cal.setTime(date);
		int zoneOffset = cal.get(Calendar.ZONE_OFFSET);
		int dstOffset = cal.get(Calendar.DST_OFFSET);
		cal.add(Calendar.MILLISECOND, -(zoneOffset + dstOffset));
		return cal.getTimeInMillis();
	}

	/**
	 * 取得月最后一天
	 * 
	 * @param date
	 * @return
	 */
	// public static Date getLastDateOfMonth(Date date) {
	// Calendar c = getCalendar();
	// c.setTime(date);
	// c.set(Calendar.DAY_OF_MONTH, c.getActualMaximum(Calendar.DAY_OF_MONTH));
	// return c.getTime();
	// }
	public static Date getLastDateOfMonth(Date date) {
		Calendar c = getCalendar();
		c.setTime(date);
		c.set(Calendar.DAY_OF_MONTH, c.getActualMaximum(Calendar.DAY_OF_MONTH));
		c.set(Calendar.HOUR_OF_DAY, c.getActualMaximum(Calendar.HOUR_OF_DAY));
		c.set(Calendar.MINUTE, c.getActualMaximum(Calendar.MINUTE));
		c.set(Calendar.SECOND, c.getActualMaximum(Calendar.SECOND));
		return c.getTime();
	}

	public static Date addYear(Date date, int yn) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.add(Calendar.YEAR, yn);
		Date result = cal.getTime();
		return result;
	}

	public static Date addMonth(Date date, int nMonth) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.add(Calendar.MONTH, nMonth);
		Date result = cal.getTime();
		return result;
	}

	public static Date addDay(Date date, int nDay) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.add(Calendar.DATE, nDay);
		Date result = cal.getTime();
		return result;
	}

	public static Date addHours(Date date, int hours) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.add(Calendar.HOUR, hours);
		Date result = cal.getTime();
		return result;
	}

	public static String formatDate(Date date, String format) {
		if (date == null)
			return null;
		SimpleDateFormat bartDateFormat = new SimpleDateFormat(format);
		String dateString = bartDateFormat.format(date);
		return dateString;
	}

	public static boolean isDate(String str) {
		String regex = "^[0-9]{4}\\-[0-9]{1,2}\\-[0-9]{1,2}$";
		return str.matches(regex);
	}

	public static boolean isTime(String str) {
		String regex = "^[0-9]{2}:[0-9]{1,2}:[0-9]{1,2}$";
		return str.matches(regex);
	}

	public static boolean isDateTime(String str) {
		String regex = "^[0-9]{4}\\-[0-9]{1,2}\\-[0-9]{1,2} [0-9]{2}:[0-9]{1,2}$";
		return str.matches(regex);
	}

	public static Date parseDateTime(String dateString, String format) {
		DateFormat dateFormat = new SimpleDateFormat(format);
		Date date = null;
		if (dateString == null || dateString.trim().equals("null")) {
			return null;
		}
		try {
			date = dateFormat.parse(dateString);
		} catch (ParseException ignored) {
			ignored.printStackTrace();
		}

		return date;
	}

	public static int getWokingDays(Date beginDate, Date endDate) {
		if (beginDate == null) {
			beginDate = new Date();
		}
		if (endDate == null) {
			endDate = new Date();
		}
		Calendar d1 = Calendar.getInstance();
		d1.setTimeInMillis(beginDate.getTime());
		Calendar d2 = Calendar.getInstance();
		d2.setTimeInMillis(endDate.getTime());

		return getWorkingDay(d1, d2);
	}

	public static int getDaysBetween(Calendar d1, Calendar d2) {
		if (d1.after(d2)) { // swap dates so that d1 is start and d2 is end
			Calendar swap = d1;
			d1 = d2;
			d2 = swap;
		}

		int days = d2.get(Calendar.DAY_OF_YEAR) - d1.get(Calendar.DAY_OF_YEAR);
		int y2 = d2.get(Calendar.YEAR);
		if (d1.get(Calendar.YEAR) != y2) {
			d1 = (Calendar) d1.clone();
			do {
				days += d1.getActualMaximum(Calendar.DAY_OF_YEAR);
				d1.add(Calendar.YEAR, 1);
			} while (d1.get(Calendar.YEAR) != y2);
		}
		return days;
	}

	public static int getDaysBetween(String dateS, String dateE) {

		try {
			Date begin = parseDateTime(dateS, YYYYMMDDS);
			Date end = parseDateTime(dateE, YYYYMMDDS);
			Calendar d1 = Calendar.getInstance();
			d1.setTime(begin);

			Calendar d2 = Calendar.getInstance();
			d1.setTime(end);
			return getDaysBetween(d1, d2);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return 0;
	}

	/**
	 * 计算2个日期之间的相隔天数
	 *
	 * @param d1
	 * @param d2
	 * @return
	 */
	public static int getWorkingDay(Calendar d1, Calendar d2) {
		int result = -1;
		if (d1.after(d2)) { // swap dates so that d1 is start and d2 is end
			Calendar swap = d1;
			d1 = d2;
			d2 = swap;
		}

		int betweendays = getDaysBetween(d1, d2);

		int charge_date = 0;
		int charge_start_date = 0;// 开始日期的日期偏移量
		int charge_end_date = 0;// 结束日期的日期偏移量
		// 日期不在同一个日期内
		int stmp;
		int etmp;
		stmp = 7 - d1.get(Calendar.DAY_OF_WEEK);
		etmp = 7 - d2.get(Calendar.DAY_OF_WEEK);
		if (stmp != 0 && stmp != 6) {// 开始日期为星期六和星期日时偏移量为0
			charge_start_date = stmp - 1;
		}
		if (etmp != 0 && etmp != 6) {// 结束日期为星期六和星期日时偏移量为0
			charge_end_date = etmp - 1;
		}
		// }
		result = (getDaysBetween(getNextMonday(d1), getNextMonday(d2)) / 7) * 5 + charge_start_date - charge_end_date;
		// System.out.println("charge_start_date>" + charge_start_date);
		// System.out.println("charge_end_date>" + charge_end_date);
		// System.out.println("between day is-->" + betweendays);
		return result;
	}

	public static String getChineseWeek(Calendar date) {
		final String dayNames[] = { "星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六" };

		int dayOfWeek = date.get(Calendar.DAY_OF_WEEK);

		// System.out.println(dayNames[dayOfWeek - 1]);
		return dayNames[dayOfWeek - 1];

	}

	public static String getChineseWeek(Date date) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		final String dayNames[] = { "星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六" };
		int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);

		// System.out.println(dayNames[dayOfWeek - 1]);
		return dayNames[dayOfWeek - 1];
	}

	/**
	 * 获得日期的下一个星期一的日期
	 * 
	 * @param date
	 * @return
	 */
	public static Calendar getNextMonday(Calendar date) {
		Calendar result = null;
		result = date;
		do {
			result = (Calendar) result.clone();
			result.add(Calendar.DATE, 1);
		} while (result.get(Calendar.DAY_OF_WEEK) != 2);
		return result;
	}

	/**
	 * @param d1
	 * @param d2
	 * @return
	 */
	public static int getHolidays(Calendar d1, Calendar d2) {
		return getDaysBetween(d1, d2) - getWorkingDay(d1, d2);

	}

	public static int getDateHour(Date date) {
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		return c.get(Calendar.HOUR_OF_DAY);
	}

	public static int getDateMinute(Date date) {
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		return c.get(Calendar.MINUTE);
	}

	public static final String YYYYMMDDHHMMSS = "yyyy-MM-dd HH:mm:ss";
	public static final String YYYYMMDDHHMM = "yyyy-MM-dd HH:mm";
	public static final String YYYYMMDD = "yyyy-MM-dd";
	public static final String YYYYMMDDS = "yyyyMMdd";
	public static final String YYYYMM = "yyyyMM";
	public static final String YYYY = "yyyy";

	/**
	 * 数字转换日期
	 * 
	 * @param lDate
	 *            long/1000的数据
	 * @return Date
	 */
	public static Date numberToDate(Long lDate) {
		if (null == lDate) {
			return null;
		}
		Date date = new Date();
		date.setTime(lDate.longValue() * ((long) 1000));
		return date;

	}

	/**
	 * 返回某天的开始时间
	 * 
	 * @param date
	 * @return
	 */
	public static Date begin(Date date) {
		if (null == date) {
			return null;
		}
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		c.set(Calendar.HOUR, 0);
		c.set(Calendar.SECOND, 0);
		c.set(Calendar.MINUTE, 0);
		return c.getTime();
	}

	/**
	 * 返回某天的结束时间
	 * 
	 * @param date
	 * @return
	 */
	public static Date end(Date date) {
		if (null == date) {
			return null;
		}
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		c.set(Calendar.HOUR, 23);
		c.set(Calendar.SECOND, 59);
		c.set(Calendar.MINUTE, 59);
		return c.getTime();
	}

	public static String cha(Date date1, Date date2) {
		StringBuffer str = new StringBuffer();
		if (null != date1 && null != date2 && date2.getTime() > date1.getTime()) {
			long cha = (date2.getTime() - date1.getTime()) / 1000;
			int hor = (int) cha / 3600;
			if (0 != hor) {
				str.append(hor).append("小时");
			}
			int secd = (int) cha % 3600 / 60;
			if (0 != secd) {
				str.append(secd).append("分");
			}
			int miao = (int) cha % 60;
			if (0 != miao) {
				str.append(miao).append("秒");
			}
		}
		return str.toString();
	}

	public static boolean isSameDay(Date d1, Date d2) {
		if (null == d1 || null == d2) {
			return false;
		}
		String d1Str = formatDate(d1, "yyyy-MM-dd");
		return d1Str.equals(formatDate(d2, "yyyy-MM-dd"));
	}

	/**
	 * 取两个日期的月数
	 * 
	 * @param d1
	 * @param d2
	 * @return
	 */
	public static int getBetweenMonth(Date d1, Date d2) {
		if (null == d1 || null == d2) {
			return 0;
		}
		if (d1.after(d2)) {
			Date d = d1;
			d1 = d2;
			d2 = d;
		}
		Calendar c = Calendar.getInstance();
		c.setTime(d2);
		int total = c.get(Calendar.YEAR) * 12 + c.get(Calendar.MONTH);
		c.setTime(d1);
		total = total - (c.get(Calendar.YEAR) * 12 + c.get(Calendar.MONTH));
		return total;
	}

	public static int getBetweenYear(Date d1, Date d2) {
		if (null == d1 || null == d2) {
			return 0;
		}
		if (d1.after(d2)) {
			Date d = d1;
			d1 = d2;
			d2 = d;
		}
		Calendar c = Calendar.getInstance();
		c.setTime(d2);
		int total = c.get(Calendar.YEAR);
		c.setTime(d1);
		total = total - c.get(Calendar.YEAR);
		return total;
	}

	public static Date getLastWeekBeginDay(Date date) {
		Calendar cadr = Calendar.getInstance(Locale.CHINA);
		cadr.setTime(date);
		int day = cadr.get(Calendar.DAY_OF_WEEK);
		cadr.add(Calendar.DAY_OF_YEAR, -(day - 2 + 7));
		return cadr.getTime();
	}

	public static Date getLastWeekEndDay(Date date) {
		Calendar cadr = Calendar.getInstance(Locale.CHINA);
		cadr.setTime(date);
		int day = cadr.get(Calendar.DAY_OF_WEEK);
		cadr.add(Calendar.DAY_OF_YEAR, -(day - 1));
		return cadr.getTime();
	}

	public static Date getThisWeekDay(int weekday) {
		Date date = new Date();
		Calendar cadr = Calendar.getInstance(Locale.CHINA);
		cadr.setTime(date);
		if (cadr.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) {
			if (weekday != Calendar.SUNDAY) {
				cadr.add(Calendar.DAY_OF_YEAR, -7);
			} else {
				cadr.set(Calendar.DAY_OF_WEEK, weekday);
			}
		} else {
			if (weekday == Calendar.SUNDAY) {
				cadr.add(Calendar.DAY_OF_YEAR, 7);
			} else {
				cadr.set(Calendar.DAY_OF_WEEK, weekday);
			}

		}

		cadr.set(Calendar.DAY_OF_WEEK, weekday);
		cadr.set(Calendar.HOUR_OF_DAY, 0);
		cadr.set(Calendar.MINUTE, 0);
		cadr.set(Calendar.SECOND, 0);
		cadr.set(Calendar.MILLISECOND, 0);

		return cadr.getTime();
	}

	private static Calendar getCalendar() {
		Calendar c = Calendar.getInstance();
		c.setFirstDayOfWeek(FIRST_DAY_OF_WEEK);
		return c;
	}

	public static void main(String[] args) {
		System.out.println(formatDate(getThisWeekDay(Calendar.MONDAY), YYYYMMDD));
		System.out.println(formatDate(getThisWeekDay(Calendar.SUNDAY), YYYYMMDD));
	}

	/**
	 * 返回当前月YYYYMM
	 * 
	 * @return
	 */
	public static int getCurrentMonthInt() {
		SimpleDateFormat sdf = new SimpleDateFormat(YYYYMM);
		return Integer.parseInt(sdf.format(new Date()));
	}

	/**
	 * 获得当天日期，不含时分秒
	 * 
	 * @return
	 */
	public static Date getTodayDate() {
		Calendar cal = Calendar.getInstance();
		cal.set(Calendar.HOUR_OF_DAY, 0);
		cal.set(Calendar.MINUTE, 0);
		cal.set(Calendar.SECOND, 0);
		cal.set(Calendar.MILLISECOND, 0);

		return new Date(cal.getTimeInMillis());
	}

	/**
	 * 根据时间和小时间隔得到一个新的时间
	 * 
	 * @return
	 */
	public static Date addDate(Date date, double hour) {

		// SimpleDateFormat format = new
		// SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		if (date == null)
			return null;

		int integer = 0;
		int remainder = 0;

		integer = (int) Math.floor(hour);
		remainder = (int) (hour * 10) % 10;

		// String aimDate = "";
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.add(Calendar.HOUR_OF_DAY, integer);
		cal.add(Calendar.MINUTE, remainder * 6);

		return cal.getTime();
	}

	/**
	 * 取两时间间隔小时/分钟
	 * 
	 * @return
	 */
	public static double getHourInt(Date lastDate, Date nextDate) {
		double hour = 0.0;
		double time = 0.0;

		if (lastDate != null && nextDate != null) {
			time = (lastDate.getTime() - nextDate.getTime()) / HOUR_VARIABLE;
		}
		if (time > 0) {
			hour = time / 60;
			hour = new Double(hour).doubleValue();
			BigDecimal initHour = new BigDecimal(hour);
			BigDecimal ho = initHour.setScale(1, initHour.ROUND_HALF_UP);
			hour = ho.doubleValue();
			// hour=Math.round(hour*10)/10;
		}
		return hour;
	}

	/**
	 * 获得当天日期，不含时分秒
	 * 
	 * @return
	 */
	public static Date getToday() {
		Calendar cal = Calendar.getInstance();
		cal.set(Calendar.HOUR_OF_DAY, 0);
		cal.set(Calendar.MINUTE, 0);
		cal.set(Calendar.SECOND, 0);
		cal.set(Calendar.MILLISECOND, 0);

		// cal.add(Calendar.DATE, 1);
		return new Date(cal.getTimeInMillis());
	}

	/**
	 * 获得指定日期前一天日期，不含时分秒
	 * 
	 * @param date
	 * @return
	 */
	public static Date getYesterday(Date date) {
		Calendar c = Calendar.getInstance();
		if (date == null) {
			date = new Date();
		}
		c.setTime(date);

		c.set(Calendar.HOUR_OF_DAY, 0);
		c.set(Calendar.MINUTE, 0);
		c.set(Calendar.SECOND, 0);
		c.set(Calendar.MILLISECOND, 0);

		c.add(Calendar.DATE, -1);
		return new Date(c.getTimeInMillis());
	}

	/**
	 * 获得指定日期后一天日期，不含时分秒
	 * 
	 * @param date
	 * @return
	 */
	public static Date getTomorrow(Date date) {
		Calendar c = Calendar.getInstance();
		if (date == null) {
			date = new Date();
		}
		c.setTime(date);

		c.set(Calendar.HOUR_OF_DAY, 0);
		c.set(Calendar.MINUTE, 0);
		c.set(Calendar.SECOND, 0);
		c.set(Calendar.MILLISECOND, 0);

		c.add(Calendar.DATE, +1);
		return new Date(c.getTimeInMillis());
	}

	public static String getTimeIntOfDateBeforeParam(int monthNum) {
		Date date = new Date();
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.add(Calendar.MONTH, -monthNum);
		return formatDate(cal.getTime(), YYYYMMDDS);
	}

	public static int getTimeIntAsIntegerOfDateBeforeParam(int monthNum) {
		Date date = new Date();
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.add(Calendar.MONTH, -monthNum);
		return Integer.parseInt(formatDate(cal.getTime(), YYYYMMDDS));
	}

}
